home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Source.bin / ImageButton.java < prev    next >
Text File  |  1998-09-04  |  18KB  |  618 lines

  1. package symantec.itools.awt;
  2.  
  3. import java.awt.AWTException;
  4. import java.awt.Color;
  5. import java.awt.Dimension;
  6. import java.awt.Event;
  7. import java.awt.Graphics;
  8. import java.awt.Image;
  9. import java.awt.MediaTracker;
  10. import java.awt.image.FilteredImageSource;
  11. import java.net.URL;
  12. import java.beans.PropertyVetoException;
  13. import java.beans.PropertyChangeListener;
  14. import java.beans.VetoableChangeListener;
  15. import java.beans.PropertyChangeEvent;
  16. import java.text.MessageFormat;
  17. import java.util.ResourceBundle;
  18.  
  19. //    01/18/97    RKM    Changed setImageURL to handle getImage returning null, added call to invalidate
  20. //    01/29/97    TWB    Integrated changes from Macintosh
  21. //    05/29/97    MSH    Updated to support Java 1.1
  22. //     07/08/97    LAB    Changed the way the button is drawn.  Now it uses the offscreen
  23. //                    Image.  Cleaned up the drawing code to be more universal.
  24. //                    Added pressed and disabled images for those states.
  25. //                    Changed data member url to imageURL.
  26. //                    Added a preferedSize() method.
  27. //    07/13/97    RKM    Fixed misspelling of prefered
  28. //  07/30/97    CAR marked fields transient as needed
  29. //                  implemented readObject
  30. //     08/05/97    LAB    Added a call to clipRect in the updateButtonImage method to clip subsequent
  31. //                    drawings to the internal button area (sans border and bevel). This should be
  32. //                    removed when the VM interprets the base class' call to clipRect correctly.
  33. //                    removed scale and center protected data members.  Added imageStyle protected
  34. //                    data member.  Added public data members to define ImageStyles.  Deprecated
  35. //                    setScaleMode, isScaleMode, setCenterMode, and isCenterMode.  Added
  36. //                    ImageStyle property.
  37. //     08/06/97    LAB    Removed the call to clipRect; now uses the base classes buttonImageGraphics
  38. //                    Graphics to draw with, which inherits the clipping.
  39. //  08/28/97    CAR "erase" image if Image URL is set to null
  40. //  09/04/98    MSH Fixed problem where default imageButton reports bogus image-loading error at
  41. //                  runtime (#43428)
  42.  
  43. /**
  44.  * The ImageButton component is similar to a regular button except that it
  45.  * displays an image on the button's face. The image to use is specified with
  46.  * a URL.
  47.  * <p>
  48.  * Use an ImageButton to:
  49.  * <UL>
  50.  * <DT>╖ Display an image in a button instead of text.</DT>
  51.  * <DT>╖ Generate a train of action events while the user presses the button.</DT>
  52.  * </UL>
  53.  * <p>
  54.  * @version 1.1, August 5, 1997
  55.  * @author Symantec
  56.  */
  57. public class ImageButton extends ButtonBase
  58. {
  59.     /**
  60.      * A constant indicating the image is to be tiled in the size of this component.
  61.      */
  62.     public static final int IMAGE_TILED = 0;
  63.     /**
  64.      * A constant indicating the image is to be centered in the size of this component.
  65.      */
  66.     public static final int IMAGE_CENTERED = 1;
  67.     /**
  68.      * A constant indicating the image is to be scaled to fit the size of this component.
  69.      */
  70.     public static final int IMAGE_SCALED_TO_FIT = 2;
  71.     /**
  72.      * A constant indicating the image is to be drawn normally in the upper left corner.
  73.      */
  74.     public static final int IMAGE_NORMAL = 3;
  75.  
  76.     /**
  77.      * Constructs a new default ImageButton. Image scaling is off and center mode on.
  78.      */
  79.     public ImageButton()
  80.     {
  81.         try
  82.         {
  83.             setImageStyle(IMAGE_CENTERED);
  84.         }
  85.         catch (PropertyVetoException exc) {}
  86.     }
  87.  
  88.     /**
  89.      * Sets the URL of the image to display in the button.
  90.      * @param u the URL of the image to display
  91.      * @see #getImageURL
  92.      * @exception PropertyVetoException
  93.      * if the specified property value is unacceptable
  94.      */
  95.     public void setImageURL(URL u) throws PropertyVetoException
  96.     {
  97.         if ( u.getFile() == "/" )   // default
  98.             return;
  99.  
  100.         URL oldValue = imageURL;
  101.  
  102.         vetos.fireVetoableChange( "ImageURL", oldValue, u );
  103.  
  104.         // Remove old images
  105.         enabledImage = null;
  106.         if (disabledImage != null)
  107.             disabledImage.flush();
  108.         disabledImage = null;
  109.         if (pressedImage != null)
  110.             pressedImage.flush();
  111.         pressedImage = null;
  112.  
  113.         // Load new image
  114.  
  115.         imageURL = u;
  116.         if (imageURL != null) {
  117.             Image image = getToolkit().getImage(imageURL);
  118.             if (image != null)
  119.             {
  120.                 MediaTracker mt = new MediaTracker(this);
  121.                 if (mt != null)
  122.                 {
  123.                     try
  124.                     {
  125.                         mt.addImage(image, 0);
  126.                         mt.waitForAll();
  127.                     }
  128.                     catch (InterruptedException ie)
  129.                     {
  130.                     }
  131.  
  132.                     if (mt.isErrorAny())
  133.                     {
  134.                         Object[] args = { image.toString() };
  135.                         System.err.println(MessageFormat.format(errors.getString("ErrorLoadingImage"), args));
  136.                         return;
  137.                     }
  138.  
  139.                     enabledImage    = image;
  140.                     disabledImage    = createImage(new FilteredImageSource(image.getSource(), new symantec.itools.awt.image.FadeFilter(0.333)));
  141.                     pressedImage    = createImage(new FilteredImageSource(image.getSource(), new symantec.itools.awt.image.DarkenFilter(0.250)));
  142.  
  143.                     changes.firePropertyChange( "ImageURL", oldValue, u );
  144.                 }
  145.             }
  146.         }
  147.         repaint();
  148.     }
  149.  
  150.     /**
  151.      * Returns the URL of the image being displayed in the button.
  152.      * @see #setImageURL
  153.      */
  154.     public URL getImageURL()
  155.     {
  156.         return imageURL;
  157.     }
  158.  
  159.     /**
  160.      * Sets the new panel image style.
  161.      * @param newStyle the new panel image style, one of
  162.      * IMAGE_TILED, IMAGE_CENTERED, IMAGE_SCALED_TO_FIT, or IMAGE_NORMAL.
  163.      * @exception PropertyVetoException
  164.      * if the specified property value is unacceptable
  165.      * @see #getImageStyle
  166.      * @see #IMAGE_TILED
  167.      * @see #IMAGE_CENTERED
  168.      * @see #IMAGE_SCALED_TO_FIT
  169.      * @see #IMAGE_NORMAL
  170.      */
  171.     public void setImageStyle(int newStyle) throws PropertyVetoException
  172.     {
  173.         if (newStyle != imageStyle)
  174.         {
  175.             Integer oldValue = new Integer(imageStyle);
  176.             Integer newValue = new Integer(newStyle);
  177.  
  178.             vetos.fireVetoableChange("ImageStyle", oldValue, newValue);
  179.  
  180.             imageStyle = newStyle;
  181.             repaint();
  182.  
  183.             changes.firePropertyChange("ImageStyle", oldValue, newValue);
  184.         }
  185.     }
  186.  
  187.     /**
  188.      * Gets the current panel image style.
  189.      * @return the current panel image style, one of
  190.      * IMAGE_TILED, IMAGE_CENTERED, IMAGE_SCALED_TO_FIT, or IMAGE_NORMAL.
  191.      * @see #setImageStyle
  192.      * @see #IMAGE_TILED
  193.      * @see #IMAGE_CENTERED
  194.      * @see #IMAGE_SCALED_TO_FIT
  195.      */
  196.     public int getImageStyle()
  197.     {
  198.         return imageStyle;
  199.     }
  200.  
  201.     /**
  202.      * @deprecated
  203.      * @see #setImageStyle
  204.      * @exception PropertyVetoException
  205.      * if the specified property value is unacceptable
  206.      */
  207.     public void setScaleMode(boolean flag) throws PropertyVetoException
  208.     {
  209.         if (flag)
  210.         {
  211.             setImageStyle(IMAGE_SCALED_TO_FIT);
  212.         }
  213.         else
  214.         {
  215.             setImageStyle(IMAGE_NORMAL);
  216.         }
  217.     }
  218.  
  219.     /**
  220.      * @deprecated
  221.      * @see #getImageStyle
  222.      */
  223.     public boolean isScaleMode()
  224.     {
  225.         return (getImageStyle() == IMAGE_SCALED_TO_FIT);
  226.     }
  227.  
  228.     /**
  229.      * @deprecated
  230.      * @see #isScaleMode
  231.      */
  232.     public boolean getScaleMode()
  233.     {
  234.         return isScaleMode();
  235.     }
  236.  
  237.     /**
  238.      * @deprecated
  239.      * @see #setImageStyle
  240.      * @exception PropertyVetoException
  241.      * if the specified property value is unacceptable
  242.      */
  243.     public void setCenterMode(boolean flag) throws PropertyVetoException
  244.     {
  245.         if (flag)
  246.         {
  247.             setImageStyle(IMAGE_CENTERED);
  248.         }
  249.         else
  250.         {
  251.             setImageStyle(IMAGE_NORMAL);
  252.         }
  253.     }
  254.  
  255.     /**
  256.      * @deprecated
  257.      * @see #getImageStyle
  258.      */
  259.     public boolean isCenterMode()
  260.     {
  261.         return (getImageStyle() == IMAGE_CENTERED);
  262.     }
  263.  
  264.     /**
  265.      * @deprecated
  266.      * @see #isCenterMode
  267.      */
  268.     public boolean getCenterMode()
  269.     {
  270.         return isCenterMode();
  271.     }
  272.  
  273.     /**
  274.      * Is the given image style valid for this button.
  275.      * @param i the given image style
  276.      * @return true if the given image style is acceptable, false if not.
  277.      */
  278.     public boolean isValidImageStyle(int i)
  279.     {
  280.         switch(i)
  281.         {
  282.                case IMAGE_TILED:
  283.             case IMAGE_CENTERED:
  284.             case IMAGE_SCALED_TO_FIT:
  285.             case IMAGE_NORMAL:
  286.                 return true;
  287.             default:
  288.                 return false;
  289.         }
  290.     }
  291.  
  292.     /**
  293.      * Returns the recommended dimensions to properly display this component.
  294.      * This is a standard Java AWT method which gets called to determine
  295.      * the recommended size of this component.
  296.      */
  297.     public Dimension getPreferredSize()
  298.     {
  299.         Dimension defaultSize = super.getPreferredSize();
  300.  
  301.         if (enabledImage == null)
  302.             return defaultSize;
  303.  
  304.         return new Dimension(defaultSize.width + enabledImage.getWidth(this), defaultSize.height + enabledImage.getHeight(this));
  305.     }
  306.  
  307.     /**
  308.      * Tells this component that it has been added to a container.
  309.      * This is a standard Java AWT method which gets called by the AWT when
  310.      * this component is added to a container. Typically, it is used to
  311.      * create this component's peer.
  312.      *
  313.      * It has been overridden here to hook-up event listeners.
  314.      *
  315.      * @see #removeNotify
  316.      */
  317.     public synchronized void addNotify()
  318.     {
  319.         super.addNotify();
  320.         errors = ResourceBundle.getBundle("symantec.itools.resources.ErrorsBundle");
  321.  
  322.         //Hook up listeners
  323.         if (styleVeto == null)
  324.         {
  325.             styleVeto = new StyleVeto();
  326.             addImageStyleListener(styleVeto);
  327.         }
  328.     }
  329.  
  330.     /**
  331.      * Tells this component that it is being removed from a container.
  332.      * This is a standard Java AWT method which gets called by the AWT when
  333.      * this component is removed from a container. Typically, it is used to
  334.      * destroy the peers of this component and all its subcomponents.
  335.      *
  336.      * It has been overridden here to unhook event listeners.
  337.      *
  338.      * @see #addNotify
  339.      */
  340.     public synchronized void removeNotify()
  341.     {
  342.         //Unhook listeners
  343.         if (styleVeto != null)
  344.         {
  345.             removeImageStyleListener(styleVeto);
  346.             styleVeto = null;
  347.         }
  348.  
  349.         super.removeNotify();
  350.     }
  351.  
  352.     /**
  353.      * Adds a listener for all event changes.
  354.      * @param listener the listener to add.
  355.      * @see #removePropertyChangeListener
  356.      */
  357.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  358.     {
  359.         super.addPropertyChangeListener(listener);
  360.         changes.addPropertyChangeListener(listener);
  361.     }
  362.  
  363.     /**
  364.      * Removes a listener for all event changes.
  365.      * @param listener the listener to remove.
  366.      * @see #addPropertyChangeListener
  367.      */
  368.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  369.     {
  370.         super.removePropertyChangeListener(listener);
  371.         changes.removePropertyChangeListener(listener);
  372.     }
  373.  
  374.     /**
  375.      * Adds a vetoable listener for all event changes.
  376.      * @param listener the listener to add.
  377.      * @see #removeVetoableChangeListener
  378.      */
  379.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
  380.     {
  381.         super.addVetoableChangeListener(listener);
  382.         vetos.addVetoableChangeListener(listener);
  383.     }
  384.  
  385.     /**
  386.      * Removes a vetoable listener for all event changes.
  387.      * @param listener the listener to remove.
  388.      * @see #addVetoableChangeListener
  389.      */
  390.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
  391.     {
  392.         super.removeVetoableChangeListener(listener);
  393.         vetos.removeVetoableChangeListener(listener);
  394.     }
  395.  
  396.     /**
  397.      * Adds a listener for the ImageStyle property changes.
  398.      * @param listener the listener to add.
  399.      * @see #removeImageStyleListener(java.beans.PropertyChangeListener)
  400.      */
  401.     public synchronized void addImageStyleListener(PropertyChangeListener listener)
  402.     {
  403.         changes.addPropertyChangeListener("ImageStyle", listener);
  404.     }
  405.  
  406.     /**
  407.      * Removes a listener for the ImageStyle property changes.
  408.      * @param listener the listener to remove.
  409.      * @see #addImageStyleListener(java.beans.PropertyChangeListener)
  410.      */
  411.     public synchronized void removeImageStyleListener(PropertyChangeListener listener)
  412.     {
  413.         changes.removePropertyChangeListener("ImageStyle", listener);
  414.     }
  415.  
  416.     /**
  417.      * Adds a vetoable listener for the ImageStyle property changes.
  418.      * @param listener the listener to add.
  419.      * @see #removeImageStyleListener(java.beans.VetoableChangeListener)
  420.      */
  421.     public synchronized void addImageStyleListener(VetoableChangeListener listener)
  422.     {
  423.         vetos.addVetoableChangeListener("ImageStyle", listener);
  424.     }
  425.  
  426.     /**
  427.      * Removes a vetoable listener for the ImageStyle property changes.
  428.      * @param listener the listener to remove.
  429.      * @see #addImageStyleListener(java.beans.VetoableChangeListener)
  430.      */
  431.     public synchronized void removeImageStyleListener(VetoableChangeListener listener)
  432.     {
  433.         vetos.removeVetoableChangeListener("ImageStyle", listener);
  434.     }
  435.  
  436.     /**
  437.      * This is the PropertyChangeEvent handling inner class for the constrained ImageStyle property.
  438.      * Handles vetoing BevelHeights that are not valid.
  439.      */
  440.     class StyleVeto implements java.beans.VetoableChangeListener, java.io.Serializable
  441.     {
  442.         /**
  443.          * This method gets called when an attempt to change the constrained ImageStyle property is made.
  444.          * Ensures the given image style is valid for this button.
  445.          *
  446.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  447.          *             event source and the property that has changed.
  448.          * @exception PropertyVetoException if the recipient wishes the property
  449.          *              change to be rolled back.
  450.          */
  451.         public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
  452.         {
  453.             int i = ((Integer)e.getNewValue()).intValue();
  454.             if (!isValidImageStyle(i))
  455.             {
  456.                 throw new PropertyVetoException(errors.getString("InvalidImageStyle") + i, e);
  457.             }
  458.         }
  459.     }
  460.  
  461.     /**
  462.      * Draws the button in the buttonImage offscreen image.
  463.      * @see symantec.itools.awt.ButtonBase#updateButtonImage
  464.      */
  465.     protected void updateButtonImage()
  466.     {
  467.         super.updateButtonImage();
  468.  
  469.         Image img;
  470.  
  471.         if(pressed)
  472.             img = pressedImage;
  473.         else
  474.             img = isEnabled() ? enabledImage : disabledImage;
  475.  
  476.  
  477.         Dimension s        = size();
  478.         int x            = bevel + 1 + pressedAdjustment;
  479.           int y            = bevel + 1 + pressedAdjustment;
  480.         int w            = s.width    - bevel - bevel - 2;
  481.         int h            = s.height    - bevel - bevel - 2;
  482.  
  483.         if (img == null) {
  484.             buttonImageGraphics.clearRect(x, y, w, h);
  485.             return;
  486.         }
  487.  
  488.         int imageWidth    = img.getWidth(this);
  489.         int imageHeight    = img.getHeight(this);
  490.  
  491.         switch(imageStyle)
  492.         {
  493.             case IMAGE_CENTERED:
  494.             default:
  495.             {
  496.                 buttonImageGraphics.drawImage
  497.                     (img, x + ((w - imageWidth) / 2), y + ((h - imageHeight) / 2), this);
  498.  
  499.                 break;
  500.             }
  501.             case IMAGE_TILED:
  502.             {
  503.                 //Calculate number of images that should be drawn horizontally
  504.                 int numHImages = w / imageWidth;
  505.  
  506.                 //Don't forget remainders
  507.                 if (w % imageWidth != 0)
  508.                     numHImages++;
  509.  
  510.                 //Calculate number of images that should be drawn vertically
  511.                 int numVImages = h / imageHeight;
  512.  
  513.                 //Don't forget remainders
  514.                 if (h % imageHeight != 0)
  515.                     numVImages++;
  516.  
  517.                 int hOff;
  518.                 int vOff = y;
  519.                 for (int vCount = 0; vCount < numVImages; vCount++)
  520.                 {
  521.                     hOff = x;
  522.                     for (int hCount = 0; hCount < numHImages; hCount++)
  523.                     {
  524.                         buttonImageGraphics.drawImage(img, hOff, vOff, imageWidth, imageHeight, this);
  525.  
  526.                         //Increment to next column
  527.                         hOff += imageWidth;
  528.                     }
  529.  
  530.                     //Increment to next row
  531.                     vOff += imageHeight;
  532.                 }
  533.                 break;
  534.             }
  535.             case IMAGE_SCALED_TO_FIT:
  536.             {
  537.                 buttonImageGraphics.drawImage(img, x, y, w, h, this);
  538.                 break;
  539.             }
  540.             case IMAGE_NORMAL:
  541.             {
  542.                 buttonImageGraphics.drawImage(img, x, y, this);
  543.                 break;
  544.             }
  545.         }
  546.     }
  547.  
  548.     private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException
  549.     {
  550.         in.defaultReadObject();
  551.  
  552.         if (imageURL != null) {
  553.             Image image = getToolkit().getImage(imageURL);
  554.             if (image != null)
  555.             {
  556.                 MediaTracker mt = new MediaTracker(this);
  557.                 if (mt != null)
  558.                 {
  559.                     try
  560.                     {
  561.                         mt.addImage(image, 0);
  562.                         mt.waitForAll();
  563.                     }
  564.                     catch (InterruptedException ie)
  565.                     {
  566.                     }
  567.  
  568.                     if (mt.isErrorAny())
  569.                     {
  570.                         Object[] args = { image.toString() };
  571.                         System.err.println(MessageFormat.format(errors.getString("ErrorLoadingImage"), args));
  572.                         return;
  573.                     }
  574.  
  575.                     enabledImage    = image;
  576.                     disabledImage    = createImage(new FilteredImageSource(image.getSource(), new symantec.itools.awt.image.FadeFilter(0.333)));
  577.                     pressedImage    = createImage(new FilteredImageSource(image.getSource(), new symantec.itools.awt.image.DarkenFilter(0.250)));
  578.                 }
  579.             }
  580.         }
  581.  
  582.     }
  583.  
  584.     /**
  585.      * Determines how to draw the image.
  586.      */
  587.     protected int imageStyle;
  588.  
  589.     /**
  590.      * The URL for the button's image
  591.      */
  592.     protected URL imageURL = null;
  593.  
  594.     /**
  595.      * The normally displayed image
  596.      */
  597.     transient protected Image enabledImage = null;
  598.  
  599.     /**
  600.      * The image displayed when the button is disabled
  601.      */
  602.     transient protected Image disabledImage    = null;
  603.  
  604.     /**
  605.      * The image displayed when the button is pressed
  606.      */
  607.     transient protected Image pressedImage = null;
  608.     /**
  609.      * Error strings.
  610.      */
  611.     transient protected ResourceBundle errors;
  612.  
  613.     private StyleVeto styleVeto = null;
  614.     private symantec.itools.beans.VetoableChangeSupport vetos   = new symantec.itools.beans.VetoableChangeSupport(this);
  615.     private symantec.itools.beans.PropertyChangeSupport changes = new symantec.itools.beans.PropertyChangeSupport(this);
  616.  
  617. }
  618.